;*******************************************************************************
; Director - Windows
;
; Copyright (C) 2003, Nick Craig-Wood and Philip Ludlam
;
;This program is free software; you can redistribute it and/or modify it under
;the terms of the GNU General Public License as published by the Free Software
;Foundation; either version 2 of the License, or (at your option) any later
;version.
;
;This program is distributed in the hope that it will be useful, but WITHOUT ANY
;WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
;PARTICULAR PURPOSE. See the GNU General Public License for more details.
;
;You should have received a copy of the GNU General Public License along with
;this program; if not, write to the Free Software Foundation, Inc., 59 Temple
;Place - Suite 330, Boston, MA 02111-1307, USA
;
;*******************************************************************************
;----h- Director.s.Windows
; Name
;   Windows
;
; Purpose
;   Handle windows; their creation, deletion,
;   and relevant events from Wimp_Poll
;------
;*******************************************************************************


		TTL	> Windows

		GET	OSLib:oslib.hdr.OS
		GET	OSLib:oslib.hdr.Wimp
		GET	OSLib:oslib.hdr.WimpReadSysInfo
		GET	AsmLib2:hdr.RegsBoth
		GET	AsmLib2:hdr.MacrosBoth
		GET	h.WorkSpace
		GET	h.ListMacros
		GET	h.Constants
		GET	AsmLib2:hdr.Debug
		GET	h.Memory
		GET	h.Messages
		GET	h.ModuleHead
		GET	h.BMG
		GET	h.Task
		GET	h.Menus

		AREA	|Windows|, CODE, READONLY


;*******************************************************************************
;----s- Director.s.Windows.WindowBlock
; Name
;   WindowBlock
;
; Purpose
;   WindowBlock structure
;
; Source


				^	0
WindowBlock_link		#	4
WindowBlock_name		#	4
WindowBlock_status		#	4
WindowBlock_window		#	4
WindowBlock_indirect		#	4
WindowBlock_command		#	4
WindowBlock_handle		#	4
WindowBlock_callevery		#	4
WindowBlock_timer		#	4
WindowBlock_temp		#	4
WindowBlock_open		#	4
WindowBlock_background		#	4
WindowBlock_persist		#	4	; persist capability
WindowBlock_tornoff		#	4	; persist status
WindowBlock			EQU	:INDEX: @


;------
;*******************************************************************************


;*******************************************************************************
; Variables local to Windows
; These are allocated from a block in the main workspace
;*******************************************************************************



			^	(:INDEX: WindowsVars), wp
; Help request vars.

HelpRequest_WindowHandle	#	4	; Used to store window handle of last help request
HelpRequest_IconHandle		#	4	; Used to store icon handle of last help request

			ASSERT	@ <= EndWindowsVars


;*******************************************************************************
;----f- Director.s.Windows.WindowSetVars
; Name
;   WindowSetVars
;
; Purpose
;   This sets the system variables Director$Window and Director$Icon
;   and Director$Buttons .
;   It may return an error
;
; Entry
;   r0 = window handle
;   r1 = icon handle
;   r2 = buttons
;
; Exit
;   If an error occured:
;     r0 = pointer to valid error block
;     VS
;   Otherwise
;     VC
;------
;*******************************************************************************


WindowSetVars	ROUTINE	"r0-r4", EXPORT
		MOV	r4, r0			; r4 = handle

		ADR	r0, icon$l		; r0  name
		BL	SetVarValN		; set the system variable
		BVS	error$l

		ADR	r0, window$l		; r0  name
		MOV	r1, r4
		BL	SetVarValN		; set the system variable
		BVS	error$l

		ADR	r0, buttons$l		; r0  name
		MOV	r1, r2
		BL	SetVarValN		; set the system variable
		BVS	error$l

ok$l		EXIT

error$l		EXIT_ERR

window$l	DCB	"$Name.$Window", 0
icon$l		DCB	"$Name.$Icon", 0
buttons$l	DCB	"$Name.$Buttons", 0
		ALIGN


;*******************************************************************************
;----f- Director.s.Windows.WindowRunCommand
; Name
;   WindowRunCommand
;
; Purpose
;   This runs a command, setting the system variables up first
;   It may return an error
;
; Entry
;   r0 = window handle
;   r1 = icon handle
;   r2 = buttons
;   r3  command
;   r11  WindowBlock
;
; Exit
;   If an error occured:
;     r0 = pointer to a valid error block
;     VS
;   Otherwise
;     VC
;------
;*******************************************************************************


WindowRunCommand	ROUTINE	"r0-r4"

		TEQ	r3, #0
		EXIT	EQ				; return if there isn't a command

		BL	WindowSetVars			; set the variables up
		BVS	error$l

		ADR	r0, name$l			; r0  name
		LDR	r1, [r11, #WindowBlock_name]	; r1  value
		MOV	r4, #OS_VartypeLiteralString
		BL	SetVarVal			; set the system variable
		BVS	error$l

		MOV	r0, r3
		BL	StartWimpTask			; run the command
		BVS	error$l

ok$l		EXIT

error$l		EXIT_ERR

name$l		DCB	"$Name.$WindowName", 0
		ALIGN


;*******************************************************************************
;----f- Director.s.Windows.WindowBlockFind
; Name
;   WindowBlockFind
;
; Purpose
;   This finds the given window block in the window list or returns
;   a pointer to the previous item
;
; Entry
;   r0  name of window
;
; Exit
;   r0  WindowBlock
;   r1  previous window block (if found)
;   Flags:
;     EQ means found
;     NE means not found
;------
;*******************************************************************************


WindowBlockFind	ROUTINE	"r2-r4"

		ADR	r4, WindowsAnchor		; r4  list anchor

loop$l		ListWalk	r4, r2			; r2  previous, r4  current
		BEQ	notfound$l

		LDR	r1, [r4, #WindowBlock_name]
		BL	strcmpi				; to_find - current
		BGT	loop$l				; continue until alphabetical place found
		BNE	notfound$l

found$l		MOV	r0, r4				; point to current WindowBlock
		MOV	r1, r2
		SetZ					; set Z (ie EQ)
		EXIT

notfound$l	MOV	r0, r4				; point to current WindowBlock
		MOV	r1, r2
		ClearZ					; reset Z (ie NE)
		EXIT


;*******************************************************************************
;----f- Director.s.Windows.WindowBlockFindNotDeleting
; Name
;   WindowBlockFindNotDeleting
;
; Purpose
;   This finds the given window block in the window list or returns
;   a pointer to the previous item
;
; Entry
;   r0  name of window
;
; Exit
;   r0  WindowBlock
;   r1  previous window block (if found)
;   Flags:
;     EQ means found
;     NE means not found
;------
;*******************************************************************************


WindowBlockFindNotDeleting	ROUTINE	"r2-r4"

		ADR	r4, WindowsAnchor		; r4  list anchor

loop$l		ListWalk	r4, r2			; r2  previous, r4  current
		BEQ	notfound$l

		LDR	r1, [r4, #WindowBlock_name]
		BL	strcmpi				; to_find - current
		BGT	loop$l				; continue until alphabetical place found
		BNE	notfound$l
		LDR	r3, [r4, #WindowBlock_status]
		CMP	r3, #Window_Delete
		BEQ	loop$l

found$l		MOV	r0, r4				; point to current WindowBlock
		MOV	r1, r2
		SetZ					; set Z (ie EQ)
		EXIT

notfound$l	MOV	r0, r4				; point to current WindowBlock
		MOV	r1, r2
		ClearZ					; reset Z (ie NE)
		EXIT


;*******************************************************************************
;----f- Director.s.Windows.WindowBlockFindHandle
; Name
;   WindowBlockFindHandle
;
; Purpose
;   This finds the window block which has the handle given open
;
; Entry
;   r0 = window handle
;
;
; Exit
;   r0  WindowBlock
;   r1  previous window block (if found)
;   Flags:
;     EQ means found
;     NE means not found
;------
;*******************************************************************************


WindowBlockFindHandle	ROUTINE	"r2-r4"

		MOV	r2, r0				; r2 = handle to find
		ADR	r0, WindowsAnchor		; r0  WindowBlock

find$l		ListWalk	r0, r1			; r0  WindowBlock, r1  previous
		BEQ	notfound$l
		LDR	lr, [r0, #WindowBlock_handle]
		CMP	lr, r2
		BNE	find$l

found$l		SetZ					; set Z (ie EQ)
		EXIT

notfound$l	ClearZ					; reset Z (ie NE)
		EXIT


;*******************************************************************************
;----f- Director.s.Windows.WindowBlockFindStatus
; Name
;   WindowBlockFindStatus
;
; Purpose
;   This finds the window block which has the status
;
; Entry
;   r0 = status
;
;
; Exit
;   r0  WindowBlock
;   r1  previous window block (if found)
;   Flags:
;     EQ means found
;     NE means not found
;------
;*******************************************************************************


WindowBlockFindStatus	ROUTINE	"r2-r4"

		MOV	r2, r0				; r2 = status to find
		ADR	r0, WindowsAnchor		; r0  WindowBlock

find$l		ListWalk	r0, r1			; r0  WindowBlock, r1  previous
		BEQ	notfound$l
		LDR	lr, [r0, #WindowBlock_status]
		CMP	lr, r2
		BNE	find$l

found$l		SetZ					; set Z (ie EQ)
		EXIT

notfound$l	ClearZ					; reset Z (ie NE)
		EXIT


;*******************************************************************************
;----f- Director.s.Windows.WindowBlockCreate
; Name
;   WindowBlockCreate
;
; Purpose
;   This creates a new window block and links it into the end of the list
;   supplied. It initialises all the fields in the window block
;
; Entry
;   r0  name for window
;   r1  template name to base window on
;   r2  file name
;   r3  command to call (or 0)
;   r4 = frequency to call in seconds (or 0)
;   r5 = temp
;   r6 = background or not (not implemented)
;   r7 = does it stay open if torn off or not? (not implemented)
;   r8 = set what window flags when torn off? (i.e. add close icon - not implemented)
;
; Exit
;   If an error occured:
;     r0 = pointer to a valid error block
;     VS
;   Otherwise
;     r0  window block
;     VC
;------
;*******************************************************************************


WindowBlockCreate	ROUTINE_SF	"r1-r11", EXPORT
template$l	#	StringSize
message$l	#	Wimp_Message
		END_SF

		MOV	r8, r2				; r8  file name
		MOV	r10, r0				; r10  name

		MOV	r0, r1
		ADR	r1, template$l
		BL	strcpy				; write word aligned template name

kill$l		MOV	r0, r10				; name
		BL	WindowBlockFindNotDeleting	; r0  window block, r1  previous
		BNE	exitkill$l
		BL	WindowBlockDestroy
		B	kill$l

exitkill$l	MOV	r7, r1				; r7  link

		TEQ	r8, #0
		MOVEQ	r11, #0				; show no block created
		BEQ	exit$l				; end if we are deleting only

		MOV	r0, #WindowBlock
		BL	malloc
		BVS	error$l
		MOV	r11, r0				; r11  WindowBlock
		MOV	r1, #WindowBlock
		BL	memclear			; clear the window block to 0

		MOV	r0, r10
		BL	strdup
		BVS	error$l
		MOV	r10, r0				; r10  dup-ed name of window
		STR	r10, [r11, #WindowBlock_name]	; store the name of the icon

		MOVS	r0, r3				; command
		BLNE	strdup
		BVS	error$l
		STR	r0, [r11, #WindowBlock_command]	; store the name of the command to run

		STR	r4, [r11, #WindowBlock_callevery]
		STR	r5, [r11, #WindowBlock_temp]
		STR	r6, [r11, #WindowBlock_background]

		Link	r11, r7, lr			; link the block into the correct place in the list

		; Start a wimp task

		MOV	r9, #0				; r9 holds error number for this segment

	BL	StartTask
	MOV	r10, r0

		MOV	r1, r8				; r1  file name
		SWI	XWimp_OpenTemplate
		BVS	load_error$l

		MOV	r1, #-1				; discover sizes needed for template
		ADR	r5, template$l			; template name
		MOV	r6, #0				; first call
		SWI	XWimp_LoadTemplate		; r1 = size of window, r2 = size of indirect
		BVS	load_error2$l
		TEQ	r6, #0
		BEQ	load_error2a$l

		MOV	r0, r1
		BL	malloc
		BVS	load_error2$l
		STR	r0, [r11, #WindowBlock_window]
		MOV	r1, r0				; r1  buffer for template

		MOV	r0, r2
		BL	malloc
		BVS	load_error2$l
		STR	r0, [r11, #WindowBlock_indirect]
		ADD	r3, r0, r2			; r3  byte following workspace
		MOV	r2, r0				; r2  workspace for indirect icons

		MOV	r4, #-1				; no fonts in template
		ADR	r5, template$l			; template name
		MOV	r6, #0				; first call
		SWI	XWimp_LoadTemplate		; actually load the template in this time
		BVS	load_error2$l

		MOV	r0, #$Name._PollWord_CreateWindow
		BL	ORR_PollWord
		B	closedown$l

		;

load_error2a$l	ADR	r0, ErrWindowNotFound
		BL	MessageErrorLookup

load_error2$l	MOVVS	r9, r0				; write error number
		SWI	XWimp_CloseTemplate
		B	closedown$l
load_error$l	MOVVS	r9, r0				; write error number
closedown$l	MOV	r0, r10

	BL	StopTask
	MOVS	r0, r9

		BNE	error2$l			; if error report it

		; wimp task stopped

exit$l		MOV	r0, r11				; r0  window block
		ClearV
		EXIT					; exit with no error

error2$l	SetV
error$l		EXIT					; exit with error

ErrWindowNotFound	ERROR	"$WindowNotFound", Error_WindowNotFound


;*******************************************************************************
;----f- Director.s.Windows.WindowBlockDestroy
; Name
;   WindowBlockDestroy
;
; Purpose
;   This destroys a window block and unlinks it from the list
;   It releases any memory also attached
;
; Entry
;   r0  menu block
;   r1  previous menu block
;
; Exit
;   none
;------
;*******************************************************************************


WindowBlockDestroy	ROUTINE_SF		"r0-r4,r11", EXPORT
handle$l	#	Wimp_W
		END_SF

		MOV	r11, r0				; r11  WindowBlock
		MOV	r4, r1				; r4  previous

		LDR	r0, [r11, #WindowBlock_handle]
		MOV	r1, #0
		MOV	r2, #Wimp_ClickDelete
		LDR	r3, [r11, #WindowBlock_command]
		BL	WindowRunCommand		; run the delete command
							; ignore any error

		LDR	r0, Status
		CMP	r0, #$Name._Status_Quit
		BEQ	dying$l

		; Close the window now and mark it for deletion when we
		; are next Director.

		LDR	r0, [r11, #WindowBlock_handle]
		CMP	r0, #0
		BEQ	branch1$l
		STR	r0, handle$l
		ADR	r1, handle$l
		SWI	XWimp_CloseWindow		; close window if created

branch1$l	MOV	r0, #Window_Delete
		STR	r0, [r11, #WindowBlock_status]

		MOV	r0, #$Name._PollWord_DeleteWindow
		BL	ORR_PollWord
		EXIT


dying$l         ; We are being killed

		LDR	r0, [r11, #WindowBlock_handle]
		CMP	r0, #0
		BEQ	branch2$l
		STR	r0, handle$l
		ADR	r1, handle$l
		SWI	XWimp_DeleteWindow		; delete window if created

branch2$l	UnLink	r11, r4, lr			; unlink the WindowBlock

		LDR	r0, [r11, #WindowBlock_name]	; free attached items
		BL	free

		LDR	r0, [r11, #WindowBlock_window]
		BL	free

		LDR	r0, [r11, #WindowBlock_indirect]
		BL	free

		LDR	r0, [r11, #WindowBlock_command]
		BL	free

		LDR	r2, [r11, #WindowBlock_link]

		MOV	r0, r11				; free block
		BL	free

		EXIT


;*******************************************************************************
;----f- Director.s.Windows.WindowBlockOpen
; Name
;   WindowBlockOpen
;
; Purpose
;   This opens a window
;
; Entry
;   r0  window name
;
; Exit
;   If an error occured:
;     r0 = pointer to a valid error block
;     VS
;   Otherwise
;     r0 = window handle
;     VC
;------
;*******************************************************************************


WindowBlockOpen	ROUTINE	"r1-r4, r11", EXPORT

		BL	WindowBlockFind
		BNE	error$l
		MOV	r11, r0				; r11  WindowBlock

		MOV	lr, #1
		STR	lr, [r11, #WindowBlock_open]	; mark as open
		LDR	lr, [r11, #WindowBlock_background]
		CMP	lr, #0
		MOVEQ	lr, #0
		STREQ	lr, [r11, #WindowBlock_timer]	; reset timer if not background

		LDR	r0, [r11, #WindowBlock_handle]
created$l	MOV	r1, #0
		MOV	r2, #Wimp_ClickOpen
		LDR	r3, [r11, #WindowBlock_command]
		BL	WindowRunCommand		; run the start up command (preserves r0)

		EXIT

error$l		ADR	r0, ErrWindowNotFound
		BL	MessageErrorLookup
		SetV
		EXIT


;*******************************************************************************
;----f- Director.s.Windows.WindowBlockIsClosed
; Name
;   WindowBlockIsClosed
;
; Purpose
;   This should be called after the window has been closed
;
; Entry
;   r11  WindowBlock
;
; Exit
;   If an error occured:
;     r0 = pointer to a valid error block
;     VS
;   Otherwise
;     VC
;------
;*******************************************************************************


WindowBlockIsClosed	ROUTINE	"r0-r4", EXPORT

		LDR	r0, [r11, #WindowBlock_handle]	; get the handle
		CMP	r0, #0
		BEQ	ok$l				; if handle is 0 then no need to close

		MOV	r1, #0
		MOV	r2, #Wimp_ClickClose
		LDR	r3, [r11, #WindowBlock_command]
		BL	WindowRunCommand		; run the shut down command
		BVS	error$l

ok$l		ClearV
		EXIT

error$l		EXIT_ERR


;*******************************************************************************
;----f- Director.s.Windows.WindowBlockClose
; Name
;   WindowBlockClose
;
; Purpose
;   This closes a window
;
; Entry
;   r0 = window handle
;
; Exit
;   If an error occured:
;     r0 = pointer to a valid error block
;     VS
;   Otherwise
;     VC
;------
;*******************************************************************************


WindowBlockClose	ROUTINE	"r0-r4, r11", EXPORT

		BL	WindowBlockFindHandle
		BNE	error2$l
		MOV	r11, r0				; r11  WindowBlock, r0  window block, r1  previous

		LDR	lr, [r11, #WindowBlock_temp]
		CMP	lr, #0
		BEQ	perm$l				; if the window is temporary then delete it
		BL	WindowBlockDestroy		; r0  window block, r1  previous
		B	ok$l

perm$l		LDR	r0, [r11, #WindowBlock_handle]	; get the handle
		CMP	r0, #0
		BEQ	ok$l				; if handle is 0 then no need to close

		BL	WindowBlockIsClosed
		BVS	error$l

		LDR	r0, [r11, #WindowBlock_open]
		TEQ	r0, #0
		BEQ	not_open$l
		MOV	r0, #0
		STR	r0, [r11, #WindowBlock_open]	; mark as closed

;;;; This might fail if called from the wrong context...
		ADD	r1, r11, #WindowBlock_handle	; point to handle
		SWI	XWimp_CloseWindow		; close the window
		BVS	error$l

not_open$l
ok$l		ClearV
		EXIT

error2$l	ADR	r0, ErrWindowNotFound
		BL	MessageErrorLookup
		SetV
error$l		EXIT_ERR


;*******************************************************************************
;----f- Director.s.Windows.WindowBlockListDestroy
; Name
;   WindowBlockListDestroy
;
; Purpose
;   This destroys all the window blocks in the list
;
; Entry
;   none
;
; Exit
;   none
;------
;*******************************************************************************


WindowBlockListDestroy	ROUTINE	"r0-r3", EXPORT

		ADR	r0, WindowsAnchor

loop$l		ListWalkForDestruction	r0, r1, r2
		BEQ	exitloop$l
		BL	WindowBlockDestroy
		B	loop$l

exitloop$l	EXIT


;*******************************************************************************
;----f- Director.s.Windows.WindowBlockListNull
; Name
;   WindowBlockListNull
;
; Purpose
;   This gives CPU time to any of the windows that are asking for it
;
; Entry
;   none
;
; Exit
;
;   If an error occured:
;     r0 = pointer to a valid error block
;     VS
;   Otherwise
;     VC
;------
;*******************************************************************************


WindowBlockListNull	ROUTINE_SF	"r0-r4, r11", EXPORT
state$l		#	Wimp_WindowState
		END_SF

		ADR	r11, WindowsAnchor

loop$l		ListWalk	r11, lr
		BEQ	ok$l

		; Calculate open-ness of window if we think it is open
		; We need to do this because if a window is opened off
		; a menu we don't get close events for it

		LDR	r0, [r11, #WindowBlock_open]
		TEQ	r0, #0
		BEQ	process$l				; if not open then don't read open-ness
		LDR	r0, [r11, #WindowBlock_handle]
		STR	r0, state$l + Wimp_WindowState_w
		ADR	r1, state$l
		SWI	XWimp_GetWindowState			; check window is still open
		BVS	error$l
		LDR	r0, state$l + Wimp_WindowState_flags
		TST	r0, #Wimp_WindowOpen
		BNE	process$l
		LDR	r0, [r11, #WindowBlock_handle]
		BL	WindowBlockClose			; mark the window as closed
		BVS	error$l
process$l

		LDR	r2, [r11, #WindowBlock_callevery]
		TEQ	r2, #0					; if callevery is 0 then no CPU required
		BEQ	loop$l

		LDR	r0, [r11, #WindowBlock_open]
		LDR	r1, [r11, #WindowBlock_background]
		ORRS	r0, r0, r1
		BEQ	loop$l					; if background OR open then do it

		LDR	r1, [r11, #WindowBlock_timer]
		ADD	r1, r1, #1				; another second has gone by
		CMP	r1, r2					; have we reached the limit of seconds?
		MOVGE	r1, #0
		STR	r1, [r11, #WindowBlock_timer]		; update timer
		BLT	loop$l

		; Call the command
		LDR	r0, [r11, #WindowBlock_handle]
		TEQ	r0, #0
		BEQ	loop$l					; don't bother if the window is shut
		MOV	r1, #0
		MOV	r2, #Wimp_ClickNull
		LDR	r3, [r11, #WindowBlock_command]
		BL	WindowRunCommand			; run the null command
		BVS	error$l
		B	loop$l

ok$l		ClearV
		EXIT

error$l		EXIT_ERR


;*******************************************************************************
;----f- Director.s.Windows.DoDirectorWindow
; Name
;   DoDirectorWindow
;
; Purpose
;   This creates a new window
;
; Entry
;   none
;
; Exit
;   none
;------
;*******************************************************************************


Help_$Name.Window	FOREXPORT
	[	OSVersion = 310
		DCB	"Create a new window from the given template file and "
		DCB	"name. The window is referred to by the name of its "
		DCB	"template or the alias name if supplied.", 13
	|
		DCB	"Help_DirectorWindow", 0
	]

Syntax_$Name.Window	FOREXPORT
	[	OSVersion = 310
		DCB	"Syntax: *$Name.Window <template_name> "
		DCB	"[-alias <name>] "
		DCB	"[-file <template_file>] "
		DCB	"[-command <text>] "
		DCB	"[-callevery <seconds>] "
		DCB	"[-temp] [-background] [-remove]"
		DCB	0
	|
		DCB	"Syntax_DirectorWindow", 0
	]
		ALIGN

Args_$Name.Window	DCB	"/g,alias/g,file/g,command/g,callevery/e, temp/s,background/s,persist/s,remove/s", 0
; + "tearable/s,tear_flags/g"
		ALIGN

Star_$Name.Window	FOREXPORT
		LDR	wp, [r12]
Do$Name.Window	SaveRegs
		ROUTINE_SF	NONE
scratch$l	#	0
arg_template$l	#	4
arg_alias$l	#	4
arg_file$l	#	4
arg_command$l	#	4
arg_callevery$l	#	4
arg_temp$l	#	4
arg_background$l #	4
arg_persist$l	#	4
arg_remove$l	#	4
space$l		#	scratch_size - :INDEX: @
		END_SF

		MOV	r1, r0				; translate given string
		ADR	r0, Args_$Name.Window
		ADR	r2, scratch$l
		MOV	r3, #scratch_size
		SWI	XOS_ReadArgs
		BVS	ErrorReturn

		LDR	r0, arg_template$l
		BL	sort_out_gstrans
		LDR	r0, arg_alias$l
		BL	sort_out_gstrans
		LDR	r0, arg_file$l
		BL	sort_out_gstrans
		LDR	r0, arg_command$l
		BL	sort_out_gstrans

		LDR	r1, arg_template$l
		CMP	r1, #0
		BEQ	must_supply_template$l		; r1  template name

		LDR	r2, arg_file$l			; r2  template file name

		LDR	lr, arg_remove$l		; file name = 0 to delete the window
		TEQ	lr, #0
		MOVNE	r2, #0

		LDR	r3, arg_command$l		; r3  command to call

		LDR	r0, arg_callevery$l
		CMP	r0, #0				; default priority is 0
		BLNE	read_eval
		MOV	r4, r0				; r4 = frequency to call in seconds

		LDR	r5, arg_temp$l			; this is a temporary window

		LDR	r6, arg_background$l		; background process?

		LDR	r0, arg_alias$l			; r0  name
		CMP	r0, #0
		MOVEQ	r0, r1				; name is template name if no alias supplied

		BL	WindowBlockCreate
		BVS	ErrorReturn

exit$l		B	NormalReturn

must_supply_template$l	ReportError	"$NoTemplate", Error_NoTemplate


;*******************************************************************************
;----f- Director.s.Windows.WindowClick
; Name
;   WindowClick
;
; Purpose
;   This is called when a click on a window is detected
;
; Entry
;   r11  Wimp_Pointer
;
; Exit
;   If an error occured:
;     r0 = pointer to a valid error block
;     VS
;   Otherwise
;     VC
;------
;*******************************************************************************


WindowClick	ROUTINE	"r8, r11", EXPORT

		MOV	r8, r11				; r8  Wimp_Pointer

		BL	WindowSetVars			; set variables from the Wimp_Pointer
		BVS	error$l

		LDR	r0, [r8, #Wimp_Pointer_w]
		BL	WindowBlockFindHandle
;		ADRNEL	r0, ErrWindowNotFound
;		BNE	error2$l				; temporary solution to "Window not found"
		BNE	ok$l				; Will be removed when moved over to DirectorWindow

		MOV	r11, r0				; r11  WindowBlock

		LDR	r0, [r8, #Wimp_Pointer_w]
		LDR	r1, [r8, #Wimp_Pointer_i]
		LDR	r2, [r8, #Wimp_Pointer_buttons]
		LDR	r3, [r11, #WindowBlock_command]
		BL	WindowRunCommand
		BVS	error$l

ok$l		ClearV
error$l		EXIT

;error2$l	SetV
;error$l	EXIT


;*******************************************************************************
;----f- Director.s.Windows.OpenWindowRequest
; Name
;   OpenWindowRequest
;
; Purpose
;   Handle Wimp_Poll open window requests
;
; Entry
;   r11  to Poll Space.
;
; Exit
;   none
;------
;*******************************************************************************


OpenWindowRequest	ROUTINE_SF "r0-r3, r11", EXPORT
mouseblock$l		#	Wimp_Pointer
			END_SF
							; r11  window handle
		MOV	r11, r1				; r1  window handle
		SWI	XWimp_OpenWindow
		BVS	error$l
		EXIT

error$l		BL	ShowError
		EXIT_ERR

;;;;		LDR	r0, [r11]			; r0 = window handle
;;;;		BL	WindowBlockFindHandle		; r0  WindowBlock
;;;;		BEQ	foundwindow$l
;;;;
;;;;		LDR	r0, [r11]			; r0 = window handle
;;;;		LDR	r1, SaveWindow			; is it the Save window?
;;;;		CMP	r0, r1
;;;;		LDRNE	r1, KeysWindow			; is it the Keys window?
;;;;		CMPNE	r0, r1
;;;;		LDRNE	r1, InfoWindow			; is it the Info window?
;;;;		CMPNE	r0, r1
;;;;		BEQ	ok$l
;;;;
;;;;;		ADRNE	r0, ErrWindowNotFound$l
;;;;		BNE	error$l
;;;;
;;;;foundwindow$l
;;;;		MOV	r11, r0				; r11  WindowBlock
;;;;							; r0  window block
;;;;							; r1  previous
;;;;
;;;;		LDR	r1, [r11, #WindowBlock_tornoff] ; has it been torn off?
;;;;		CMP	r1, #2
;;;;		BEQ	ok$l				; if yes, exit
;;;;
;;;;		CMP	r1, #0
;;;;		MOVEQ	r2, #1				; it's just been opened
;;;;		STREQ	r2, [r11, #WindowBlock_tornoff]	; off of the menu
;;;;		BEQ	ok$l
;;;;
;;;;				; it has either been torn off (mouse click)
;;;;				; or not (no mouse click)
;;;;
;;;;		ADR	r1, mouseblock$l
;;;;		SWI	XWimp_GetPointerInfo		; read pointer info
;;;;		BVS	error$l
;;;;
;;;;		LDR	r0, [r1, #Wimp_Pointer_buttons]
;;;;		CMP	r0, #0				; is a mouse button pressed?
;;;;		BEQ	ok$l				; the window isn't being moved, so exit
;;;;
;;;;		MOV	r1, #2
;;;;		STR	r1, [r11, #WindowBlock_tornoff]	; mark as torn off
;;;;
;;;;		LDR	r0, [r11, #WindowBlock_handle]
;;;;created$l	MOV	r1, #0
;;;;;		MOV	r2, #Wimp_ClickTornOff
;;;;		LDR	r3, [r11, #WindowBlock_command]
;;;;		BL	WindowRunCommand		; run the torn off command (preserves r0)
;;;;		BVS	error$l
;;;;
;;;;		EXIT
;;;;
;;;;ok$l	ClearV
;;;;		EXIT


;ErrWindowNotFound$l	ERROR	"$WindowNotFound", Error_WindowNotFound
;ErrOpeningWindow$l	ERROR	"$OpeningWindow", Error_OpeningWindow


;*******************************************************************************
;----f- Director.s.Windows.CloseWindowRequest
; Name
;   CloseWindowRequest
;
; Purpose
;   Handle Wimp_Poll close window requests
;
; Entry
;   r11  to Poll Space.
;
; Exit
;   none
;------
;*******************************************************************************


CloseWindowRequest	ROUTINE , 	EXPORT
		LDR	r0, [r11, #Wimp_Close_w]	; r0 = window handle

		LDR	r1, KeysWindow
		CMP	r0, r1
		EXIT	EQ				; don't close the keys window

		LDR	r1, SaveWindow
		CMP	r0, r1
;		LDRNE	r1, InfoWindow
;		CMPNE	r0, r1
		BEQ	normal$l			; deal with a normal window

		BL	WindowBlockClose		; close one of our special windows
		BVS	error$l
		EXIT

normal$l	MOV	r1, r11
		SWI	XWimp_CloseWindow
		BVS	error$l
		EXIT

error$l		BL	ShowError
		EXIT_ERR


;*******************************************************************************
;----f- Director.s.Windows.DoMessage_HelpRequest_Window
; Name
;   DoMessage_HelpRequest_Window
;
; Purpose
;   Handle help request messages for Director windows.
;
; Entry
;   r2 = window handle
;   r3 = icon handle
;
; Exit
;   r0  to help message
;   EQ if the window handle was a DirectorWindow
;   NE if the window handle was not a DirectorWindow
;------
;*******************************************************************************


DoMessage_HelpRequest_Window	ROUTINE	"r1-r3, r11", EXPORT

		MOV	r0, r2				; r0 = window handle
		BL	WindowBlockFindHandle		; r0  WindowBlock
		EXIT	NE				; exit if we can't handle it

		LDR	r1, HelpRequest_WindowHandle	; use r1 as scratch
		CMP	r1, r2				; are we getting a request for the same window handle as before?
		LDREQ	r1, HelpRequest_IconHandle
		CMPEQ	r1, r3				; are we getting a request for the same icon handle as before?
		LDREQ	r1, [r0, #WindowBlock_callevery]
		CMPEQ	r1, #0				; if callevery is 0 then the window can't have changed
		BEQ 	skipcommand$l

docommand$l	STR	r2, HelpRequest_WindowHandle	; Store window handle
		STR	r3, HelpRequest_IconHandle	; Store icon handle
		MOV	r11, r0				; r11  WindowBlock
		ADR	r0, helpvar$l
		BL	UnsetVarVal			; unset the Help variable, ignore any error
		LDR	r0, [r11, #WindowBlock_handle]
		MOV	r1, #0
		MOV	r2, #Wimp_ClickHelp
		LDR	r3, [r11, #WindowBlock_command]
		BL	WindowRunCommand		; run the get help command (preserves r0)
		BVS	error$l

skipcommand$l	ADR	r0, helpvar$l
		ADR	r1, TempSpace			; use Canonicalise as scratch
		MOV	r2, #StringSize
		MOV	r3, #0
		MOV	r4, #OS_VartypeString		; r4 = 0
		SWI	XOS_ReadVarVal

		MOVVC	r0, r1				; If we got something then null terminate the string
		MOVVC	r1, #0
		STRVCB	r1, [r0, r2]
		ADRVS	r0, defaulthelp$l		; otherwise use the default help string.
		MOVVS	r1, #0
		BLVS	MessageLookup
		BVS	error$l

		SetZ					; We can handle the Help Request.
		EXIT

error$l		BL	ShowError
		EXIT_ERR

helpvar$l	DCB	"Director$Window$Help", 0
defaulthelp$l	DCB	"Help_Window_Default", 0
		ALIGN


;*******************************************************************************
;----f- Director.s.Windows.WindowCreateWindowPollWord
; Name
;   WindowCreateWindowPollWord
;
; Purpose
;   Do the final part to create a window when we are running as Director.
;
; Entry
;   n/a
;
; Exit
;   n/a
;------
;*******************************************************************************


WindowCreateWindowPollWord	ROUTINE	"r0-r4,r11", EXPORT

start$l		MOV	r0, #Window_Create		; find a Window to be created
		BL	WindowBlockFindStatus		; r0  WindowBlock, r1  previous
		BNE	nomore$l

		MOV	r11, r0				; r11  WindowBlock
		MOV	r4, r1				; r4  previous

		LDR	r0, [r11, #WindowBlock_handle]
		CMP	r0, #0
		BNE	start$l

		LDR	r1, [r11, #WindowBlock_window]
		SWI	XWimp_CreateWindow
		BVS	error$l
		STR	r0, [r11, #WindowBlock_handle]
		MOV	r0, #Window_Running
		STR	r0, [r11, #WindowBlock_status]

		LDR	r0, [r11, #WindowBlock_window]
		BL	free
		MOV	r0, #0
		STR	r0, [r11, #WindowBlock_window]	; free window space since we don't need it

		LDR	r0, [r11, #WindowBlock_handle]
		MOV	r1, #0
		MOV	r2, #Wimp_ClickInit
		LDR	r3, [r11, #WindowBlock_command]
		BL	WindowRunCommand		; run the initialise command (preserves r0)
		BVS	error$l

		MOV	r0, r11				; r0  WindowBlock
		MOV	r1, r4				; r1  previous
		B	start$l

nomore$l
		MOV	r0, #$Name._PollWord_CreateWindow
		BL	BIC_PollWord
		EXIT

error$l		EXIT_ERR
		LTORG


;*******************************************************************************
;----f- Director.s.Windows.WindowDeleteWindowPollWord
; Name
;   WindowDeleteWindowPollWord
;
; Purpose
;   Do the final part of deleting a window when we are running as Director.
;
; Entry
;   n/a
;
; Exit
;   n/a
;------
;*******************************************************************************


WindowDeleteWindowPollWord	ROUTINE	"r0-r3", EXPORT

start$l		MOV	r0, #Window_Delete		; find a Window to be deleted
		BL	WindowBlockFindStatus		; r0  WindowBlock, r1  previous
		BNE	nomore$l

		MOV	r2, r0				; r2  WindowBlock
		MOV	r3, r1				; r3  previous

		ADD	r1, r2, #WindowBlock_handle
		SWI	XWimp_DeleteWindow		; delete the window

		LDR	r0, [r2, #WindowBlock_name]	; free attached items
		BL	free

		LDR	r0, [r2, #WindowBlock_window]
		BL	free

		LDR	r0, [r2, #WindowBlock_indirect]
		BL	free

		LDR	r0, [r2, #WindowBlock_command]
		BL	free

		UnLink	r2, r3, lr			; unlink the WindowBlock

		MOV	r0, r2				; free block
		BL	free

		MOV	r0, r2				; r0  WindowBlock
		MOV	r1, r3				; r1  previous
		B	start$l

nomore$l
		MOV	r0, #$Name._PollWord_DeleteWindow
		BL	BIC_PollWord
		EXIT

error$l		EXIT_ERR


;*******************************************************************************


Window_NoSuchWindow	ROUTINE	"", EXPORT

		ADR	r0, menu$l
		SWI	&6A100	; XDirector_Menu
		BVS	exit$l

		ADR	r0, option$l
		SWI	&6A102	; XDirector_Option
		BVS	exit$l

		MOV	r0, #0
		SWI	&6A101	; XDirector_EndMenu

exit$l		EXIT

menu$l		DCB	"\"\" NoSuchWindow -temp",0
option$l	DCB	"\"The window does not exist\" -grey",0
		ALIGN


;*******************************************************************************

		END
